#include "process.hpp"
#include <vector>
#include <algorithm> // for std::sort

// 定义一个结构体来存储候选矩形及其面积
struct CandidateRect {
    std::vector<cv::Point> corners;
    double area;
};

// 辅助函数：检查一个点周围的邻域是否为特定颜色
bool checkNeighborhoodColor(const cv::Mat& image, cv::Point center, int expected_color) {
    // 检查3x3邻域
    for (int dy = -1; dy <= 1; ++dy) {
        for (int dx = -1; dx <= 1; ++dx) {
            cv::Point current_point = center + cv::Point(dx, dy);
            // 边界检查
            if (current_point.x < 0 || current_point.x >= image.cols ||
                current_point.y < 0 || current_point.y >= image.rows) {
                return false; // 采样点超出图像边界，验证失败
            }
            if (image.at<uchar>(current_point) != expected_color) {
                return false;
            }
        }
    }
    return true;
}


std::optional<std::vector<cv::Point>> processFrame(const cv::Mat& input_frame, cv::Mat& output_binary_frame, const AppConfig& config) {
    // 1. 预处理
    cv::Mat gray_frame;
    cv::cvtColor(input_frame, gray_frame, cv::COLOR_BGR2GRAY);

    if (config.use_gaussian_blur) {
        int ksize = (config.gaussian_kernel_size % 2 == 0) ? config.gaussian_kernel_size + 1 : config.gaussian_kernel_size;
        cv::GaussianBlur(gray_frame, gray_frame, cv::Size(ksize, ksize), 0);
    }

    if (config.use_adaptive_threshold) {
        cv::adaptiveThreshold(gray_frame, output_binary_frame, 255,
                              cv::ADAPTIVE_THRESH_GAUSSIAN_C, cv::THRESH_BINARY_INV,
                              config.adaptive_block_size, config.adaptive_c);
    } else {
        cv::threshold(gray_frame, output_binary_frame, config.threshold_value, 255, cv::THRESH_BINARY_INV);
    }

    // 2. 寻找轮廓
    std::vector<std::vector<cv::Point>> contours;
    std::vector<cv::Vec4i> hierarchy;
    cv::findContours(output_binary_frame, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);

    // 3. 海选：收集所有符合条件的候选者
    std::vector<CandidateRect> candidates;
    for (int i = 0; i < contours.size(); ++i) {
        // 条件1: 拓扑结构正确 (内嵌轮廓)
        if (hierarchy[i][3] != -1 && hierarchy[hierarchy[i][3]][3] == -1) {
            std::vector<cv::Point> approx;
            double peri = cv::arcLength(contours[i], true);
            cv::approxPolyDP(contours[i], approx, config.shape_detection_epsilon * peri, true);

            // 条件2: 几何形状正确 (四边形)
            if (approx.size() == 4) {
                // 条件3: 尺寸正确 (面积大于最小阈值)
                double area = cv::contourArea(approx);
                if (area > config.min_contour_area) {
                    // 条件4: (可选) 角点颜色稳定性验证
                    if (!config.corner_check_enabled) {
                        candidates.push_back({approx, area});
                        continue; // 如果不验证，直接加入候选
                    }

                    bool all_corners_valid = true;
                    for (size_t j = 0; j < 4; ++j) {
                        cv::Point p_curr = approx[j];
                        cv::Point p_prev = approx[(j + 3) % 4];
                        cv::Point p_next = approx[(j + 1) % 4];

                        cv::Point2f v1 = p_prev - p_curr;
                        cv::Point2f v2 = p_next - p_curr;

                        v1 = v1 / cv::norm(v1);
                        v2 = v2 / cv::norm(v2);

                        cv::Point2f bisector = v1 + v2;
                        // 叉乘判断内外
                        if (v1.cross(v2) < 0) {
                            bisector = -bisector;
                        }
                        
                        cv::Point2f normal = bisector / cv::norm(bisector);
                        
                        cv::Point inner_sample = p_curr + cv::Point(normal * config.corner_check_distance);
                        cv::Point outer_sample = p_curr - cv::Point(normal * config.corner_check_distance);

                        // 注意：findContours 找的是白色物体，所以内部是白色(255)，外部是黑色(0)
                        if (!checkNeighborhoodColor(output_binary_frame, inner_sample, 255) ||
                            !checkNeighborhoodColor(output_binary_frame, outer_sample, 0)) {
                            all_corners_valid = false;
                            break;
                        }
                    }

                    if (all_corners_valid) {
                        candidates.push_back({approx, area});
                    }
                }
            }
        }
    }

    // 4. 精选：从候选者中选出最优的
    if (candidates.empty()) {
        return std::nullopt;
    }

    std::sort(candidates.begin(), candidates.end(), [](const CandidateRect& a, const CandidateRect& b) {
        return a.area > b.area;
    });

    return candidates[0].corners;
}